package com.qfedu.sem.service.impl;

import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.transaction.Transactional;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.qfedu.sem.dto.BugDto;
import com.qfedu.sem.dto.BugLogDto;
import com.qfedu.sem.po.Bug;
import com.qfedu.sem.po.BugLog;
import com.qfedu.sem.po.BugVersion;
import com.qfedu.sem.repository.BugLogRepository;
import com.qfedu.sem.repository.BugRepository;
import com.qfedu.sem.service.BugService;

import wo.bsys.vo.WoUser;
import wo.common.entity.WoPage;
import wo.common.util.WoJsonUtil;
import wo.common.util.WoUtil;
import wo.department.po.Staff;
import wo.department.repository.StaffRepository;

@Service
@Transactional
public class BugServiceImpl implements BugService {
	private static Logger LOG = LogManager.getLogger(BugServiceImpl.class);

	@Resource // @Autowired
	private BugRepository bugRepository;

	@Resource // @Autowired
	private BugLogRepository logRepository;

	@Resource // @Autowired
	private StaffRepository staffRepository;

	@Override
	public WoPage<BugDto> getPageData(Long start, Long length, String searchContent, String dir) {
		// 从dao获取数据
		Pageable pageInput = PageRequest.of(start.intValue() / length.intValue(), length.intValue());
		Page<Bug> pageData = null;
		if (WoUtil.isEmpty(searchContent)) {
			pageData = bugRepository.findAll(pageInput);
		} else {
			pageData = bugRepository.findAllByTitleLike("%" + searchContent + "%", pageInput);
		}
		// 将PO转化为DTO
		WoPage<BugDto> pr = BugDto.getPageData(pageData.getContent(), pageData.getTotalElements());
		return pr;
	}

	@Override
	public void create(BugDto dto, MultipartFile imageFile, WoUser woUser) {
		// 1.保存截图
		// 上传文件的相对路径
		if (imageFile != null && !imageFile.getOriginalFilename().equals("")) {
			String path = "bug/" + imageFile.getOriginalFilename();
			try {
				imageFile.transferTo(new File(root + path));
			} catch (Exception e) {
				e.printStackTrace();
			}
			// 设置图片的url
			dto.setImage(path);
		}
		// 2.创建PO并入库
		// Staff s = this.staffRepository.findByUserId(woUser.getId());
		dto.setCommitterId(woUser.getStaffIds());
		dto.setCommitTime(new Date());
		// 设置下一个节点为当前节点：开发修复
		dto.setCurrentNode("fix");
		Bug po = dto.createPO();
		this.bugRepository.save(po);
		// 3.构造日志并入库
		BugLog log = new BugLog();
		// 设置日志和BUG的关系数据
		log.setBug(po);
		// 设置本次提交的表单内容为json
		log.setContent(WoJsonUtil.toString(dto));
		log.setId(java.util.UUID.randomUUID().toString());
		// 设置当前节点：commit
		log.setNode("commit");
		// 设置处理人：当前用户对应的人员
		Staff s = new Staff();
		s.setId(woUser.getStaffIds());
		log.setProcesser(s);
		log.setProcessTime(new Date());
		// 保存日志
		this.logRepository.save(log);
	}

	@Override
	public BugDto getById(String id) {
		Bug po = this.bugRepository.findById(id).get();
		return new BugDto(po);
	}

	@Override
	public void fix(BugDto dto, WoUser woUser) {
		// 保存故障修复节点提交过来的表单数据
		Bug po = this.bugRepository.findById(dto.getId()).get();
		po.setConfirmBug(dto.getConfirmBug());
		po.setFixRemark(dto.getFixRemark());
		po.setFixTime(new Date());
		BugVersion version = new BugVersion();
		version.setId(dto.getFixVersionId());
		po.setFixVersion(version);
		// 设置下一个节点为当前节点：测试验证
		po.setCurrentNode("test");
		this.bugRepository.save(po);
		dto.setFixTime(po.getFixTime());
		// 2.构造日志并入库
		BugLog log = new BugLog();
		// 设置日志和BUG的关系数据
		log.setBug(po);
		// 设置本次提交的表单内容为json
		log.setContent(WoJsonUtil.toString(dto));
		log.setId(java.util.UUID.randomUUID().toString());
		// 设置当前节点：fix
		log.setNode("fix");
		// 设置处理人：当前用户对应的人员
		Staff s = new Staff();
		s.setId(woUser.getStaffIds());
		log.setProcesser(s);
		log.setProcessTime(new Date());
		// 保存日志
		this.logRepository.save(log);
	}

	@Override
	public void test(BugDto dto, WoUser woUser) {
		// 保存故障修复节点提交过来的表单数据
		Bug po = this.bugRepository.findById(dto.getId()).get();
		po.setIsOk(dto.getIsOk());
		po.setRestRemark(dto.getRestRemark());
		po.setTestTime(new Date());
		BugVersion version = new BugVersion();
		version.setId(dto.getTestVersionId());
		po.setTestVersion(version);
		// 设置下一个节点为当前节点
		if (po.getIsOk()) {
			po.setCurrentNode("end");
		} else {
			po.setCurrentNode("fix");
		}
		this.bugRepository.save(po);
		dto.setTestTime(po.getTestTime());
		//
		BugLog log = new BugLog();
		// 设置日志和BUG的关系数据
		log.setBug(po);
		// 设置本次提交的表单内容为json
		log.setContent(WoJsonUtil.toString(dto));
		log.setId(java.util.UUID.randomUUID().toString());
		// 设置当前节点
		log.setNode("test");
		// 设置处理人：当前用户对应的人员
		Staff s = new Staff();
		s.setId(woUser.getStaffIds());
		log.setProcesser(s);
		log.setProcessTime(new Date());
		// 保存日志
		this.logRepository.save(log);
	}

	@Override
	public BugLogDto getLogById(String id) {
		BugLog po = this.logRepository.findById(id).get();
		return new BugLogDto (po);
	}

	@Override
	public List<BugDto> getAll() {
		List<Bug> pos = this.bugRepository.findAllByOrderByCommitTimeDesc();
		return BugDto.getDtos(pos);
	}

	@Override
	public Map<String, Integer> getBugsByVersion(String projectId, String currentNode) {
		List<Object[]> bugs = bugRepository.findAllByProjectAndNode(projectId, currentNode);
		Map<String, Integer> map= new HashMap<String, Integer>();
		for (Object[] bug : bugs) {
			map.put(bug[0].toString(), ((Long)bug[1]).intValue());
		}
		return map;
	}
	
	/**
	 * 根据id数组删除一个或者多个故障
	 * @param id
	 */
	@Override
	public void delete(String[] id) {
		bugRepository.deleteByIdIn(id);
	}

	@Override
	public WoPage<BugDto> getPageData(Long start, Long length, String searchContent, String dir, WoUser currentUser, String staffType) {
		ExampleMatcher m = ExampleMatcher.matching();
		Bug qo = new Bug ();
		if (!WoUtil.isEmpty(searchContent)) {
			// title like
			m.withMatcher("title", GenericPropertyMatchers.contains());
			qo.setTitle(searchContent);
		}
		if (!WoUtil.isEmpty(currentUser.getStaffIds())) {
			Staff s = new Staff ();
			if ("committer".equals(staffType)) {
				// committer.id = 
				m.withMatcher("committer.id", GenericPropertyMatchers.exact());
				s.setId(currentUser.getStaffIds());
				qo.setCommitter(s);
			} else if ("fixer".equals(staffType)) {
				// fixer.id = 
				m.withMatcher("fixer.id", GenericPropertyMatchers.exact());
				s.setId(currentUser.getStaffIds());
				qo.setFixer(s);
			} else if ("tester".equals(staffType)) {
				// tester.id = 
				m.withMatcher("tester.id", GenericPropertyMatchers.exact());
				s.setId(currentUser.getStaffIds());
				qo.setTester(s);
			}
		}
		Example<Bug> ex = Example.of(qo, m);
		// 根据commitTime字段逆序
		Pageable p = PageRequest.of(start.intValue()/length.intValue(), length.intValue(), Direction.DESC, "commitTime");
		Page<Bug> page = this.bugRepository.findAll(ex, p);
		return new WoPage<BugDto> (BugDto.getDtos(page.getContent()), page.getTotalElements());
	}
}
